﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Mime
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;

    /// <summary>Represents a parameterized header field (see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
    /// 5.1.).</summary>
    /// <threadsafety static="true" instance="false"/>
    public sealed class ParameterizedHeaderField : HeaderField<ParameterizedHeaderField>
    {
        private string val;
        private readonly Dictionary<string, string> parameters =
            new Dictionary<string, string>(6, StringComparer.OrdinalIgnoreCase);

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>Initializes a new instance of the <see cref="ParameterizedHeaderField"/> class.</summary>
        /// <param name="name">The name of the header field, e.g. <see cref="HeaderFieldNames.ContentType"/>.</param>
        /// <exception cref="ArgumentException"><paramref name="name"/> is <c>null</c> or empty.</exception>
        public ParameterizedHeaderField(string name) : this(name, string.Empty)
        {
        }

        /// <summary>Gets or sets the value of the field.</summary>
        /// <exception cref="ArgumentNullException">Attempted to set to <c>null</c>.</exception>
        /// <remarks>The default value is <see cref="string.Empty"/>, which is set during construction and when the
        /// parser does not find a valid value.</remarks>
        public string Value
        {
            get
            {
                return this.val;
            }

            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }

                this.val = value;
            }
        }

        /// <summary>Gets the parameters as dictionary.</summary>
        /// <remarks>
        /// <para>The returned dictionary compares keys case-insensitively.</para>
        /// <para>Parsed values in the dictionary are never <c>null</c>.</para>
        /// </remarks>
        public IDictionary<string, string> Parameters
        {
            get { return this.parameters; }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal ParameterizedHeaderField(string name, string value) : base(name)
        {
            this.val = value;
        }

        internal sealed override void WriteTo(Stream stream)
        {
            StringBuilder bodyBuilder = new StringBuilder(this.val, this.val.Length + (this.parameters.Count * 32));

            foreach (var parameter in this.parameters)
            {
                bodyBuilder.Append("; " + parameter.Key + "=\"" + parameter.Value + "\"");
            }

            HeaderFieldHelper.FoldHeaderField(
                this.Name, new[] { new HeaderFieldBodyPart(bodyBuilder.ToString(), false) }, stream);
        }
    }
}
